package com.ruoyi.warning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.warning.ding.DingTalkWorkNoticeUtils;
import com.ruoyi.warning.domain.dto.ConfigurationDTO;
import com.ruoyi.warning.domain.entity.*;
import com.ruoyi.warning.domain.query.ConfigurationQuery;
import com.ruoyi.warning.domain.vo.ConfigurationVO;
import com.ruoyi.warning.mapper.ConfigurationMapper;
import com.ruoyi.warning.mapper.WarningConfigurationRuleRelationMapper;
import com.ruoyi.warning.service.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 告警配置表 服务实现类
 * </p>
 *
 * @author chenhc
 * @since 2025-02-06
 */
@Service
public class ConfigurationServiceImpl extends ServiceImpl<ConfigurationMapper, Configuration> implements IConfigurationService {
    @Resource
    private ConfigurationMapper configurationMapper;
    @Resource
    private IContactsService contactsService;
    @Resource
    private WarningSendService warningSendService;
    @Resource
    private IEventService eventService;
    @Resource
    private DingTalkWorkNoticeUtils dingTalkWorkNoticeUtils;
    @Resource
    private IEventDetailService eventDetailService;
    @Resource
    private IWarningConfigurationRuleRelationService relationService;
    @Resource
    private WarningConfigurationRuleRelationMapper relationMapper;
    @Override
    public TableDataInfo getConfigurationPage(ConfigurationQuery query) {
        Page<Object> page = PageHelper.startPage(query.getPageNum(),query.getPageSize());
        List<ConfigurationVO> list = configurationMapper.getList(query);
        return new TableDataInfo(list, page.getTotal());
    }

    @Override
    public List<Configuration> getConfigurationList(ConfigurationQuery query) {
        LambdaQueryWrapper<Configuration> wrapper = new QueryWrapper<Configuration>().lambda();
        return this.list(wrapper);
    }

    @Override
    public Set<String> getMonth(String id) {
        List<Configuration> list = this.list(new QueryWrapper<Configuration>().lambda().eq(Configuration::getDeviceId,id));
        Set<String> set = new HashSet<>();
        for(Configuration configuration:list){
            for(String s:configuration.getMonth().split(",")){
                set.add(s);
            }
        }
        return set;
    }

    @Override
    public String saveConfiguration(ConfigurationDTO configuration) {
        this.save(configuration);
        LambdaQueryWrapper<WarningConfigurationRuleRelation> wrapper = new LambdaQueryWrapper<WarningConfigurationRuleRelation>()
                .eq(WarningConfigurationRuleRelation::getConfigurationId,configuration.getId());
        relationService.remove(wrapper);
        List<WarningConfigurationRuleRelation> relationList = new ArrayList<>();
        for(String rule:configuration.getRules()){
            WarningConfigurationRuleRelation relation = new WarningConfigurationRuleRelation();
            relation.setConfigurationId(configuration.getId());
            relation.setRuleId(rule);
            relationList.add(relation);
        }
        relationService.saveBatch(relationList);
        return null;
    }

    @Override
    public String deleteConfiguration(List<String> ids) {
        this.removeByIds(ids);
        return null;
    }

    @Override
    public String updateConfiguration(ConfigurationDTO configuration) {
        this.updateById(configuration);
        LambdaQueryWrapper<WarningConfigurationRuleRelation> wrapper = new LambdaQueryWrapper<WarningConfigurationRuleRelation>()
                .eq(WarningConfigurationRuleRelation::getConfigurationId,configuration.getId());
        relationService.remove(wrapper);
        List<WarningConfigurationRuleRelation> relationList = new ArrayList<>();
        for(String rule:configuration.getRules()){
            WarningConfigurationRuleRelation relation = new WarningConfigurationRuleRelation();
            relation.setConfigurationId(configuration.getId());
            relation.setRuleId(rule);
            relationList.add(relation);
        }
        relationService.saveBatch(relationList);
        return null;
    }

    @Override
    public String warning(List<String> ids) throws Exception {
        //先找到对应的配置，然后根据配置的方式进行告警
        //先找短信的告警配置
        LambdaQueryWrapper<Configuration> wrapper = new QueryWrapper<Configuration>().lambda()
                .in(Configuration::getId,ids).eq(Configuration::getWarningWays,3);
        List<Configuration> list = this.list(wrapper);
//        List<ConfigurationDTO> configurationDTOList = new ArrayList<>();
        for(Configuration configuration:list){
            //根据配置的联系人id，找到联系人的联系方式
            LambdaQueryWrapper<Contacts> contactsWrapper = new QueryWrapper<Contacts>().lambda()
                    .in(Contacts::getId,configuration.getWarningContactsId());
            List<Contacts> contactsList = contactsService.list(contactsWrapper);

            //把configuration填充到ConfigurationDTO中
            ConfigurationDTO configurationDTO = new ConfigurationDTO();
            BeanUtils.copyProperties(configuration,configurationDTO);
            configurationDTO.setContacts(contactsList);
            configurationDTO.setTitle("测试事件");
            configurationDTO.setDeviceName("测试设备");
            if(ObjectUtils.isNotEmpty(configuration)){
                if(configuration.getWarningWays().contains("0")){
                    //发送电话
                    warningSendService.sendPhoneByVoice(configurationDTO);
                }
                if(configuration.getWarningWays().contains("1")){
                    //发送钉钉
                    DingTalkWorkNoticeUtils utils = new DingTalkWorkNoticeUtils();
                    String token = utils.getTokenResponse();
                    //这里是发送钉钉的文本消息，发送图片和视频用其他接口
                    utils.sendWorkNoticeText(token,configurationDTO.getDeviceName()+"发生预警:"+configurationDTO.getTitle()+"℃",configurationDTO);
                }
                if(configuration.getWarningWays().contains("2")){
                    //发送邮箱
                    warningSendService.sendEmail(configurationDTO);
                }
                if(configuration.getWarningWays().contains("3")){
                    //发送短信
                    warningSendService.sendSms(configurationDTO);
                }
            }
        }
        return null;
    }

    @Override
    public Event warningSend(Event event, EventDetail eventDetail, Configuration configuration) {
        //根据配置的联系人id，找到联系人的联系方式
        String[] ids = configuration.getWarningContactsId().split(",");
        LambdaQueryWrapper<Contacts> contactsWrapper = new QueryWrapper<Contacts>().lambda()
                .in(Contacts::getId,ids)
                .last("ORDER BY FIELD(id, " + StringUtils.join(ids,  ",") + ")");

        List<Contacts> contactsList = contactsService.list(contactsWrapper);

        //把configuration填充到ConfigurationDTO中
        ConfigurationDTO configurationDTO = new ConfigurationDTO();
        BeanUtils.copyProperties(configuration,configurationDTO);

        configurationDTO.setEventId(event.getId());
        configurationDTO.setContacts(contactsList);
        configurationDTO.setDeviceName(event.getDeviceName());
        configurationDTO.setTitle(event.getTitle());
        configurationDTO.setEventDetailId(eventDetail.getId());
//        todo
//        getWarningValue(configurationDTO);

        // 固定大小的线程池去执行任务
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        if(ObjectUtils.isNotEmpty(configuration)){
            if(configuration.getWarningWays().contains("0")) {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        warningSendService.sendPhoneByTts(configurationDTO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            if(configuration.getWarningWays().contains("1")){
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        String token = dingTalkWorkNoticeUtils.getTokenResponse();
                        try {
                            dingTalkWorkNoticeUtils.sendWorkNoticeText(token,event.getHostName()+event.getDeviceName()+" 告警："+event.getTitle(),configurationDTO);
                        } catch (Exception e) {
                            System.out.println(" 出错：" + e.getMessage());
                        }
//                        String fileId = dingTalkWorkNoticeUtils.uploadMedia(token,"file",new File(eventService.download(event)));
//                        dingTalkWorkNoticeUtils.sendWorkNoticeFile(token,fileId,configurationDTO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            if(configuration.getWarningWays().contains("2")){
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        warningSendService.sendEmail(configurationDTO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            if(configuration.getWarningWays().contains("3")){
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        warningSendService.sendSms(configurationDTO);
                    } catch (Exception e) {
                        log.error("告警发送失败: event={"+
                                event+"}, eventDetail={"+eventDetail+"}, configuration={"+configuration+"}"+e);
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                    .get(30, TimeUnit.MINUTES); // 最多等待30分钟
        } catch (Exception e) {
            // 处理超时或执行异常
            throw new RuntimeException("告警发送任务执行异常", e);
        }
        event.setIsWarning("1");
        event.setRemark("成功预警");
        eventDetail.setIsWarning("1");
        eventDetail.setRemark("成功预警");
        eventService.saveOrUpdate(event);
        eventDetailService.saveOrUpdate(eventDetail);
        return event;
    }

    @Override
    public Event warningSend(Event event, EventDetail eventDetail, ConfigurationVO configuration) {
        //根据配置的联系人id，找到联系人的联系方式
        String[] ids = configuration.getWarningContactsId().split(",");
        LambdaQueryWrapper<Contacts> contactsWrapper = new QueryWrapper<Contacts>().lambda()
                .in(Contacts::getId,ids)
                .last("ORDER BY FIELD(id, " + StringUtils.join(ids,  ",") + ")");

        List<Contacts> contactsList = contactsService.list(contactsWrapper);

        //把configuration填充到ConfigurationDTO中
        ConfigurationDTO configurationDTO = new ConfigurationDTO();
        BeanUtils.copyProperties(configuration,configurationDTO);

        configurationDTO.setEventId(event.getId());
        configurationDTO.setContacts(contactsList);
        configurationDTO.setDeviceName(event.getDeviceName());
        configurationDTO.setTitle(event.getTitle());
        configurationDTO.setEventDetailId(eventDetail.getId());
//        todo
//        getWarningValue(configurationDTO);

        // 固定大小的线程池去执行任务
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        if(ObjectUtils.isNotEmpty(configuration)){
            if(configuration.getWarningWays().contains("0")) {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        warningSendService.sendPhoneByTts(configurationDTO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            if(configuration.getWarningWays().contains("1")){
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        String token = dingTalkWorkNoticeUtils.getTokenResponse();
                        try {
                            dingTalkWorkNoticeUtils.sendWorkNoticeText(token,event.getHostName()+event.getDeviceName()+" 告警："+event.getTitle(),configurationDTO);
                        } catch (Exception e) {
                            System.out.println(" 出错：" + e.getMessage());
                        }
//                        String fileId = dingTalkWorkNoticeUtils.uploadMedia(token,"file",new File(eventService.download(event)));
//                        dingTalkWorkNoticeUtils.sendWorkNoticeFile(token,fileId,configurationDTO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            if(configuration.getWarningWays().contains("2")){
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        warningSendService.sendEmail(configurationDTO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            if(configuration.getWarningWays().contains("3")){
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        warningSendService.sendSms(configurationDTO);
                    } catch (Exception e) {
                        log.error("告警发送失败: event={"+
                                event+"}, eventDetail={"+eventDetail+"}, configuration={"+configuration+"}"+e);
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }
        }

        // 等待所有任务完成
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                    .get(30, TimeUnit.MINUTES); // 最多等待30分钟
        } catch (Exception e) {
            // 处理超时或执行异常
            throw new RuntimeException("告警发送任务执行异常", e);
        }
        event.setIsWarning("1");
        event.setRemark("成功预警");
        eventDetail.setIsWarning("1");
        eventDetail.setRemark("成功预警");
        eventService.saveOrUpdate(event);
        eventDetailService.saveOrUpdate(eventDetail);
        return event;
    }

    //todo
    private ConfigurationDTO getWarningValue(ConfigurationDTO configurationDTO) {
        //根据规则的名称，找到对应的值
        String title = configurationDTO.getTitle();
        if(title.contains("CPU")||title.contains("cpu")){

        }

        return configurationDTO;
    }

    @Override
    public Object getDetails(String id) {
        Map<String,Object> map = new HashMap<>();
        Configuration configuration = this.getById(id);
        map.put("configuration",configuration);
        LambdaQueryWrapper<WarningConfigurationRuleRelation> wrapper = new QueryWrapper<WarningConfigurationRuleRelation>().lambda()
               .eq(WarningConfigurationRuleRelation::getConfigurationId,configuration.getId());
        map.put("rules",relationService.list(wrapper));
        return map;
    }
    public static void main(String[] args) {
        String time = "2025-03-20T12:51:51";
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        LocalDateTime startTime = LocalDateTime.parse(time, formatter);
        ZonedDateTime zonedDateTime = startTime.atZone(ZoneOffset.ofHours(8));
        long start = zonedDateTime.toInstant().toEpochMilli();
        System.out.println(startTime);
        System.out.println(start);

    }
}
